﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Common;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Factories;
using FarseerPhysics.Dynamics.Contacts;

namespace chemicall
{
    class Character : dynamicEntity
    {
        public const string CHAR_ASSETNAME = "oxygen";
        public const int PLAYER_ID = 1;
        private bool grounded,lefted,righted;
        public int etat;
        private int stackImpulse = 0;
       
        //private Point screenCenter;
        State currentState = State.Idle;

        Vector2 startingPosition;
        public int compteurElec;

        KeyboardState mPreviousKeyboardState;

        SoundManager soundMan;

        public Character(/*Point screenCenter,*/ SoundManager sM)
        {
            //this.screenCenter = screenCenter;

            compteurElec = 6;
            soundMan = sM;
            etat = 0;       }


        public void LoadContent(ContentManager contentManager, World world, Vector2 position, Nullable<Rectangle> entitySize, Nullable<Rectangle> spriteSize)
        {
            base.LoadContent(contentManager, world, CHAR_ASSETNAME, position, entitySize, spriteSize, this);
            bodyFixture.OnCollision += MyOnCollision;
            body.SleepingAllowed = false;
            currAnim = 0;
        }

        public void Update(GameTime gameTime, World world)
        {

            KeyboardState aCurrentKeyboardState = Keyboard.GetState();
            Vector2 pos = body.Position;
            Position.X = pos.X;
            Position.Y = pos.Y;
            UpdateMovement(aCurrentKeyboardState);
            UpdateJump(aCurrentKeyboardState);
            mPreviousKeyboardState = aCurrentKeyboardState;

            base.Update(gameTime);

            body.SetTransform(new Vector2(Position.X, Position.Y), 0.0f);

            updateAnimation();

        }

        private void UpdateMovement(KeyboardState aCurrentKeyboardState)
        {
            speed.X = 0;
            direction.X = 0;
           // lefted = false;
            //righted = false;

            if (aCurrentKeyboardState.IsKeyDown(Keys.Left) == true)
            {
                speed.X = CONSTANTES.CHAR_SPEED;
                direction.X = CONSTANTES.MOVE_LEFT;
                flip = true;
                if (currentState != State.Jumping)
                    currentState = State.Walking;
                if (stackImpulse < 20)
                {
                    body.ApplyLinearImpulse(new Vector2(direction.X * 20000f, 0f));
                    stackImpulse++;
                }
            }
            else if (aCurrentKeyboardState.IsKeyDown(Keys.Right) == true)
            {

                speed.X = CONSTANTES.CHAR_SPEED;
                direction.X = CONSTANTES.MOVE_RIGHT;
                flip = false;
                if (currentState != State.Jumping)
                    currentState = State.Walking;
                if (stackImpulse < 20)
                {
                    body.ApplyLinearImpulse(new Vector2(direction.X * 20000f, 0f));
                    stackImpulse++;
                }
            }
            else
            {
                if (currentState != State.Jumping)
                    currentState = State.Idle;
                if (stackImpulse >= 0)
                {
                    stackImpulse--;
                }
            }
            
        }

        private void UpdateJump(KeyboardState aCurrentKeyboardState)
        {
            if (currentState == State.Walking || currentState == State.Idle)
            {
                if (aCurrentKeyboardState.IsKeyDown(Keys.Space) == true && mPreviousKeyboardState.IsKeyDown(Keys.Space) == false)
                {
                    Jump();
                }
            }

            if (currentState == State.Jumping)
            {
                if (Position.Y < startingPosition.Y - CONSTANTES.JUMP_HEIGHT)
                {
                    direction.Y = CONSTANTES.MOVE_DOWN;
                    speed = new Vector2(CONSTANTES.CHAR_SPEED, 0.0f);
                    //body.ApplyLinearImpulse(new Vector2(0.0f,-80000f));
                }
                else if (grounded && direction.Y == CONSTANTES.MOVE_DOWN)
                {
                    currentState = State.Idle;
                    bodyFixture.Friction = PhysicalEntity.DEFAULT_FRICTION;
                    direction.Y = 0.0f;
                }
            }
        }

        private void Jump()
        {
            if (grounded)
            {
                soundMan.startEvent(CONSTANTES.JUMP_SOUND_ID);
                currentState = State.Jumping;
                startingPosition = Position;
                bodyFixture.Friction = 0.0f;
                direction.Y = CONSTANTES.MOVE_UP;
                speed = new Vector2(CONSTANTES.CHAR_SPEED, CONSTANTES.CHAR_SPEED *1.5f);
                grounded = false;
            }
        }



        public bool MyOnCollision(Fixture f1, Fixture f2, Contact contact)
        {
           
            Object other;
            Object avatar = f1.Body.UserData;

            if (avatar is Character)
            { other = f2.Body.UserData; }
            else
            { other = avatar; avatar = f1.Body.UserData; }

            

            if (other is StaticEntity && !(other is Agent))
            {
                if ((other as StaticEntity).AssetName.Equals("exit"))
                {
                    if (this.etat != 0)
                        SoundManager.getInstance().startEvent(CONSTANTES.GAME_OVER_ID);
                    LevelManager.getInstance().EndLevel();
                    return true;
                }
                else
                {
                    Vector2 pos = Position;
                    Vector2 norm;
                    FixedArray2<Vector2> pts;
                    contact.GetWorldManifold(out norm, out pts);
                    if (grounded == false)
                    {
                        grounded = true;
                        grounded &= norm.Y > 0;
                    }
                    return true;
                }
            }
            else if (other is Anion)
            {
                if ((other as Anion).stable == false)
                {
                    float dist;
                    Vector2.Distance(ref (other as Anion).Position, ref Position, out dist);
                    if (dist < entitySize.Width / 2)
                    {
                        //Console.Write("l'anion n'est pas stable");
                        (other as Anion).setStable();
                        soundMan.startEvent(CONSTANTES.GAIN_SOUND_ID);
                        etat += 1;
                        if (compteurElec < CONSTANTES.MAX_ELECTRONS)
                            compteurElec++;
                        Console.WriteLine("numLevel = " + LevelManager.getInstance().getNumLevel());
                        //infoBulle
                        if (LevelManager.getInstance().getNumLevel() == 1)
                        {
                            InfoBulle.getInstance().setInfoBulle("Quand vous touchez un Anion vous gagnez un electron !", 5.0f);
                            soundMan.startEvent(CONSTANTES.BUBBLE_TIP_ID);
                        }
                        soundMan.setParameterValue(CONSTANTES.INGAME_MUSIC_ID, CONSTANTES.CHARGE_PARAMETER, (float)compteurElec / 10f);
                        return true;
                    }
                }
            }

            else if (other is Cation)
            {
                if ((other as Cation).stable == false)
                {
                    float dist;
                    Vector2.Distance(ref (other as Cation).Position, ref Position, out dist);
                    if (dist < entitySize.Width / 2)
                    {
                        ((Cation)other).setStable();
                        soundMan.startEvent(CONSTANTES.PERTE_SOUND_ID);
                        etat -= 1;
                        if (compteurElec >= CONSTANTES.MIN_ELECTRONS)
                            compteurElec--;

                        //infoBulle
                        Console.WriteLine("numLevel = " + LevelManager.getInstance().getNumLevel());
                        if (LevelManager.getInstance().getNumLevel() == 1)
                        {
                            InfoBulle.getInstance().setInfoBulle("Quand vous touchez un Cation vous perdez un electron !", 5.0f);
                            soundMan.startEvent(CONSTANTES.BUBBLE_TIP_ID);
                        }
                        soundMan.setParameterValue(CONSTANTES.INGAME_MUSIC_ID, CONSTANTES.CHARGE_PARAMETER, (float)compteurElec / 10f);
                        return true;
                    }
                }
            }  

            
            

            return false;
            
        }


        //TODO faire le getter setter comme au dessous!
        public int getNbElec()
        {
            return compteurElec;
        }

        public State state
        {
            get { return currentState; }
        }

        private void updateAnimation()
        {
            if (etat < 0) 
                currAnim = 1;
            else if (etat > 0)
                currAnim = 2;
            else
                currAnim = 0;
        }
    }
}

